#include "lock.hpp"
#include "utility.hpp"

namespace mina
{
	namespace thread
	{
		IMPL_LOGGER(Lock, logger);

		Lock::Lock()
		{
			int ret = 0;
			if ((ret = ::pthread_mutex_init(&_mutex, 0)) != 0)
			{
				LOG4CPLUS_ERROR(logger, "Lock::lock pthread_mutex_init error. errno: " << ret);
			}
		}

		Lock::~Lock()
		{
			int ret = 0;
			if ((ret = ::pthread_mutex_destroy(&_mutex)) != 0)
			{
				LOG4CPLUS_ERROR(logger, "Lock::~Lock pthread_mutex_destroy error. errno: " << ret);
			}
		}

		void Lock::lock()
		{
			int ret = 0;
			if ((ret = ::pthread_mutex_lock(&_mutex)) != 0)
			{
				LOG4CPLUS_ERROR(logger, "Lock::lock pthread_mutex_lock error. errno: " << ret);	
			}
		}

		void Lock::unlock()
		{
			int ret = 0;
			if ((ret = ::pthread_mutex_unlock(&_mutex)) != 0)
			{
				LOG4CPLUS_ERROR(logger, "Lock::unlock pthread_mutex_unlock error. errno: " << ret);
			}
		}

		bool Lock::lock(long ms)
		{
			struct timespec ts;
			Utility::get_abs_timespec(ms, ts);
			int ret = 0;
			ret = ::pthread_mutex_timedlock(&_mutex, &ts);
			if (ETIMEDOUT == ret)
			{
				return false;
			}

			if (0 != ret)
			{
				LOG4CPLUS_ERROR(logger, "Lock::lock pthread_mutex_timedlock error. errno: " << ret);
			}
			return (0 == ret);
		}

		bool Lock::try_lock()
		{
			return (::pthread_mutex_trylock(&_mutex) == 0);
		}
	}
}

